#ifndef __STD_CODE_COMPILE_EVENT_HPP__
#define __STD_CODE_COMPILE_EVENT_HPP__

#include "base_event.hpp"

namespace run_code_event_space {

struct std_code_compile_event : base_event<std_code_compile_event>  {
    template <class U>
    ProcessStatus execute_impl(run_code_context_t<U>& context);
};

template <class U>
ProcessStatus std_code_compile_event::execute_impl(run_code_context_t<U>& context) {
    ProcessStatus ps;
    if (context.judge_type.stdFile == "") {
        ps.result = LESS_STDFILES;
        ps.error = "less stdFile";
        return ps;
    }
    const RuncodeParams& params = context.params;
    const U& judge_type = context.judge_type;
    auto& [stdLang, stdCodeFile, stdBinFile, stdCompileStr, stdRunStr] = judge_type.stdCodeInfo;
    Log::instance().getOutput() << "stdCodeInfo:" << judge_type.stdCodeInfo;
    if constexpr (std::is_same_v<U, ModuleJudge>) {
        const auto& spjFiles = judge_type.spjFiles;
        const auto& spjCacheFiles = judge_type.spjCacheFiles;
        auto spjFileIt = std::find_if(spjFiles.begin(), spjFiles.end(), [&](const string& file){
            return endWith(file, "."s + params.language + "." + stdLang->suffix);
        });
        if (spjFileIt == spjFiles.end()) {
            spjFileIt = std::find_if(spjFiles.begin(), spjFiles.end(), [&](const string& file) {
                return endWith(file, "."s + stdLang->suffix);
            });
        }

        if (spjFileIt == spjFiles.end()) {
            return ProcessStatus {
                    .result = LESS_SPJFILE,
                    .error = "less [" + params.language + "] spjFile",
            };
        }

        Log::instance().getOutput() << "find correct stdFile :" << *spjFileIt << endl;

        auto index = std::distance(spjFiles.begin(), spjFileIt);
        // 仅检查是否拷贝成功,若需要更新spj文件，则删除原本的stdcache
        ps = general_execution_strategy::_copy<false>(*spjFileIt, spjCacheFiles[index], DEFAULT_LANG,
            [&]{
                std::filesystem::remove(stdCodeFile);
                return ProcessStatus{.result = RUN_OK};
            });

        if (ps.result != RUN_OK) {
            return ps;
        }
        
        Log::instance().getOutput() << "success copy spjFile form '" << *spjFileIt << "' to '" << spjCacheFiles[index] << "'" << endl;
        auto updateFun = [&]() {
            auto spjCode = fileToStr(spjCacheFiles[index]);
            auto stdCode = fileToStr(stdCodeFile);
            std::ofstream stdCodeFs{stdCodeFile};
            stdCodeFs << spjCode;
            stdCodeFs << endl;
            stdCodeFs << stdCode;

            Log::instance().getOutput() << "stdFile append ok" << endl;

            return ProcessStatus{.result = RUN_OK};
        };
        ps = general_execution_strategy::_copy<false>(judge_type.stdFile, stdCodeFile, stdLang, updateFun);
    } else {
        ps = general_execution_strategy::_copy<false>(judge_type.stdFile, stdCodeFile, stdLang);
    }
    if (ps.result != RUN_OK) {
        ps.result = SYS_ERROR;
        return ps;
    }
    ps = general_execution_strategy::_compile<false>(stdCodeFile, stdBinFile, stdCompileStr);
    if (ps.result != RUN_OK) {
        ps.result = STD_COMPILE_ERROR;
        return ps;
    }
    judge_type.stdCompileOk = true;
    return ps;
}

}

#endif /* __STD_CODE_COMPILE_EVENT_HPP__ */
